import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

import * as cookieParser from 'cookie-parser';
import * as session from 'express-session';

import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';
import { engine } from 'express-handlebars';

import { ValidationPipe } from '@nestjs/common';
import { I18nValidationPipe, I18nValidationExceptionFilter } from 'nestjs-i18n';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';

// 解决在验证其类 中使用userService provider的错误
import { useContainer } from 'class-validator';
import { HbsHelpers } from './shared/helpers';

async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(AppModule);

  // 使用useContainer 自定义验证器中支持依赖注入
  useContainer(app.select(AppModule), { fallbackOnErrors: true });

  // 配置静态文件根目录
  app.useStaticAssets(join(__dirname, '..', 'public'));
  // 配置模板的根目录
  app.setBaseViewsDir(join(__dirname, '..', 'views'));
  // 配置handlebars模板引擎
  app.engine(
    'hbs',
    engine({
      extname: '.hbs',
      runtimeOptions: {
        allowProtoMethodsByDefault: true, //允许访问原型上的方法
        allowProtoPropertiesByDefault: true, // 允许访问原型上的属性
      },
      helpers: {
        ...HbsHelpers,
      },
    }),
  );
  // 配置模板引擎,设置渲染的模板引擎为hbs
  app.set('view engine', 'hbs');

  app.use(cookieParser());
  app.use(
    session({
      secret: 'secret-key',
      resave: true,
      saveUninitialized: true,
      cookie: {
        maxAge: 1000 * 60 * 60 * 24 * 7,
      },
    }),
  );

  // 注册管道 验证参数
  // 加上transform：true dto拿到的是实体类，不加则是普通对象
  // app.useGlobalPipes(new ValidationPipe({ transform: true }));
  app.useGlobalPipes(new I18nValidationPipe({ transform: true }));
  app.useGlobalFilters(
    new I18nValidationExceptionFilter({ detailedErrors: true }),
  ); //捕获I18nValidationPipe 异常进行处理

  // 创建一个新的DocumentBuilder示例用来构建swagger
  const config = new DocumentBuilder()
    .setTitle('CMS API')
    .setDescription('CMS API 描述')
    .setVersion('1.0')
    .addTag('CMS')
    .addCookieAuth('connect.sid') //添加cookie认证方式，cookie的名称为connect.sid
    .addBearerAuth({
      //添加bearer认证方式，在请求头里添加Authorization: Bearer Token
      type: 'http',
      scheme: 'bearer',
    })
    .build();
  // 使用配置对象，创建swagger
  const document = SwaggerModule.createDocument(app, config);
  // 设置swagger模块的路径和文档对象，将swagger-ui绑定到api-docs路径上
  SwaggerModule.setup('api-docs', app, document);

  await app.listen(process.env.PORT ?? 8080);
}

bootstrap();
